//
//  ZMRefreshControl.swift
//  ZMWeiboSwift
//
//  Created by pg on 2017/7/29.
//  Copyright © 2017年 pg. All rights reserved.
//

import UIKit

let RefreshControlHeight : CGFloat = 50

//MARK:-下拉刷新控件的状态
enum ZMRefreshControlType {
    //普通状态
    case normal
    //松手就刷新
    case pulling
    //正在刷新
    case refreshing
    
    
}


class ZMRefreshControl: UIControl {

    //记录当前刷新控件的父视图
    var currentScrollView : UIScrollView?
    
   
    //MARK:- 记录下拉视图当前的状态,默认普通状态
    var refreshType: ZMRefreshControlType = .normal {
        //refreshType的set方法,在为refreshType赋值的时候就会调用这个setter方法
        didSet{
            
            switch refreshType {
                
            case .normal:
                //下拉刷新,普通状态
                //显示箭头
                imageView.isHidden = false
                //  停止风火轮
                indicatorView.stopAnimating()
                //  箭头方向恢复向下,使用动画恢复
                UIView.animate(withDuration: 0.25, animations: { 
                    
                    self.imageView.transform = CGAffineTransform.identity
                }, completion: { (isfinish) in
                    
                    //如果是从正在刷新数据状态进入的普通状态,就需要将正在刷新状态设置的视图偏移恢复
                    
                    if oldValue == .refreshing {
                        UIView.animate(withDuration: 0.25, animations: { 
                            self.currentScrollView?.contentInset.top -= RefreshControlHeight
                        })
                    }
                    
                })
                
                
            case .pulling:
                //松手就刷新状态
                //箭头调转到向上,使用动画
                UIView.animate(withDuration: 0.25, animations: { 
                    self.imageView.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
                })
                //文字显示:"松手刷新数据"
                messageLabel.text = "松手刷新数据"
                
            case .refreshing:
                //正在刷新状态
                //隐藏箭头
                imageView.isHidden = true
                //  活动指示器开始动画
                indicatorView.startAnimating()
                //  文字显示:"正在刷新..."
                messageLabel.text = "正在刷新数据..."
                //  正在刷新数据的时候设置刷新视图停留在屏幕上,由于松手之后到停留位置之间使用动画更流畅,所以加上动画
                UIView.animate(withDuration: 0.25, animations: { 
                    self.currentScrollView?.contentInset.top += RefreshControlHeight
                }, completion: { (isfinish) in
                    //动画完成之后发送刷新事件
                    self.sendActions(for: UIControlEvents.valueChanged)
                })
                
            
            }
            
            
        }
        
    }
    
    
    
    //MARK:- 懒加载箭头
    fileprivate lazy var imageView : UIImageView = {
       
        let view = UIImageView(image: #imageLiteral(resourceName: "tableview_pull_refresh"))
       
        return view
    }()
    
    //懒加载刷新消息提示框
    fileprivate lazy var messageLabel : UILabel = {
    
        let label = UILabel()
        label.text = "下拉刷新"
        label.font = UIFont.systemFont(ofSize: 12)
        label.textColor = UIColor.gray
        
        return label
    }()
    
    //MARK:- 懒加载活动指示器
    fileprivate lazy var indicatorView: UIActivityIndicatorView = {
        let view = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray)
        
        
        return view
        
    }()
    
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        
        setupUI()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    //MARK:- 添加子控件
    func setupUI(){
        
        //添加子控件
        addSubview(imageView)
        addSubview(messageLabel)
        addSubview(indicatorView)
        
        //设置子控件约束
        //禁用autosizing布局
        imageView.translatesAutoresizingMaskIntoConstraints = false
        messageLabel.translatesAutoresizingMaskIntoConstraints = false
        indicatorView.translatesAutoresizingMaskIntoConstraints = false
        //给箭头view添加约束
        addConstraint(NSLayoutConstraint(item: imageView, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: -35))
        addConstraint(NSLayoutConstraint(item: imageView, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0))
        //给messagelabel添加约束
        addConstraint(NSLayoutConstraint(item: messageLabel, attribute: .centerY, relatedBy: .equal, toItem: imageView, attribute: .centerY, multiplier: 1, constant: 0))
        addConstraint(NSLayoutConstraint(item: messageLabel, attribute: .leading, relatedBy:.equal, toItem: imageView, attribute: .trailing, multiplier: 1, constant: 0))
        
        //给活动指示器添加约束
        addConstraint(NSLayoutConstraint(item: indicatorView, attribute:.centerX, relatedBy: .equal, toItem: imageView, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0))
        
        addConstraint(NSLayoutConstraint(item: indicatorView, attribute: .centerY, relatedBy: .equal, toItem: imageView, attribute: .centerY, multiplier: 1, constant: 0))
       
    }
    
    //外部将本控件添加到其他空间上的时候就自动调用willMove方法
    override func willMove(toSuperview newSuperview: UIView?) {
        
        guard let scrollerView = newSuperview as? UIScrollView else{
            
            //父控件不存在,,解包不成功,就直接返回
            return
        }
        self.frame = CGRect(x: 0, y: -RefreshControlHeight, width: scrollerView.frame.width, height: RefreshControlHeight)
        //使用kvo记录父视图的滚动事件
        scrollerView.addObserver(self, forKeyPath: "contentOffset", options: NSKeyValueObservingOptions.new, context: nil)
        //记录当前刷新视图的父视图
        currentScrollView = scrollerView
        
    }
    
    
    //MARK:- kvo监听scrollview滚动
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        
        //读取当前scrollview的便宜值
     //   let contentOffSetY = change["NSKeyValueChangeNewKey"]
        let contentOffSetY = currentScrollView!.contentOffset.y
       
       //状态的改变
        //刷新状态可以分为拖动状态和松手状态
        //拖动的情况下:   状态在normal和pulling之间互相切换
        //松手的情况 :   当松手前是出于pulling状态的时候才能进入refreshing(正在刷新)状态
        if currentScrollView!.isDragging {
            //正在拖动的情况
            //当刷新视图的顶部还没有完全显示出来的时候,处于nomal状态,当刷新视图完全显示出来之后就要进入pulling状态(松手即刷新)状态
            let limitMaxY = -(currentScrollView!.contentInset.top + RefreshControlHeight)
            //刷新视图还没有完全显示出来,为了避免连续不断的进入到pulling状态,所以此时只有当其状态是nomal的时候才能进入pulling状态
            if contentOffSetY < limitMaxY && refreshType == .normal {
                refreshType = .pulling
            }else if contentOffSetY > limitMaxY && refreshType == .pulling{
                refreshType = .normal
            }
            
        }else{
            //没有拖动,如果松手的时候是pulling状态,那么就会进入正在刷新状态
            if refreshType == .pulling {
                refreshType = .refreshing
            }
        }
        
        
    }
    
    //MARK:- 结束刷新
    func endRefreshing(){
        refreshType = .normal
    }
    
    
    //MARK:- 析构函数
    deinit {
        //移除kvo监听
        currentScrollView?.removeObserver(self, forKeyPath: "contentOffset")
    }
    
    
}
